#include "BankingSystem.h"
#include <iostream>
#include <fstream>
#include <algorithm>
#include <ctime>
#include <iomanip>
#include <sstream>
#include <random>
using namespace std;
// 银行系统构造函数，初始化随机数生成器
BankingSystem::BankingSystem()
{
    // 初始化随机数生成器
    random_device rd;
    rng = mt19937(rd());
}

// 注册新客户，创建储蓄账户和支票账户
shared_ptr<Customer> BankingSystem::registerCustomer(const string &name)
{
    // 生成唯一的账户ID
    string savingsId = generateUniqueAccountId(true);
    string checkingId = generateUniqueAccountId(false);

    // 创建初始余额为零的账户
    auto savingsAccount = make_shared<SavingsAccount>(savingsId, name);
    auto checkingAccount = make_shared<CheckingAccount>(checkingId, name);

    // 创建客户对象
    auto customer = make_shared<Customer>(name, savingsAccount, checkingAccount);

    // 存储账户和客户信息
    accounts[savingsId] = savingsAccount;
    accounts[checkingId] = checkingAccount;
    customers.push_back(customer);

    return customer;
}

// 根据姓名查找客户
shared_ptr<Customer> BankingSystem::findCustomer(const string &name) const
{
    auto it = find_if(customers.begin(), customers.end(),
                           [&name](const shared_ptr<Customer> &customer)
                           {
                               return customer->getName() == name;
                           });

    if (it != customers.end())
    {
        return *it;
    }

    return nullptr;
}

// 根据账户ID查找账户
shared_ptr<Account> BankingSystem::findAccount(const string &accountId) const
{
    auto it = accounts.find(accountId);
    if (it != accounts.end())
    {
        return it->second;
    }

    return nullptr;
}

// 检查账户ID是否唯一
bool BankingSystem::isAccountIdUnique(const string &accountId) const
{
    return accounts.find(accountId) == accounts.end();
}

// 生成唯一的账户ID
string BankingSystem::generateUniqueAccountId(bool isSavings)
{
    uniform_int_distribution<int> branchDist(1, 9999);
    uniform_int_distribution<int> accountDist(1, 9999);
    uniform_int_distribution<int> finalDist(1, 9999);

    // 储蓄账户以6221开头，支票账户以6222开头
    string prefix = isSavings ? "6221" : "6222";

    // 生成唯一的账户ID
    string accountId;
    do
    {
        ostringstream oss;
        oss << prefix << "-"
            << setw(4) << setfill('0') << branchDist(rng) << "-"
            << setw(4) << setfill('0') << accountDist(rng) << "-"
            << setw(4) << setfill('0') << finalDist(rng);

        accountId = oss.str();
    } while (!isAccountIdUnique(accountId));

    return accountId;
}

// 存款操作
bool BankingSystem::deposit(const string &accountId, double amount, const string &note)
{
    // 检查存款金额是否为正数
    if (amount <= 0)
    {
        cerr << "Error: Deposit amount must be positive." << endl;
        return false;
    }

    // 查找账户
    auto account = findAccount(accountId);
    if (!account)
    {
        cerr << "Error: Account not found." << endl;
        return false;
    }

    // 检查账户是否支持存款
    if (!account->canDeposit())
    {
        cerr << "Error: This account type does not support direct deposits." << endl;
        return false;
    }

    // 创建交易记录
    auto transaction = make_shared<Transaction>(
        TransactionType::DEPOSIT,
        accountId,
        "", // 存款没有目标账户
        amount,
        note);

    // 记录交易
    recordTransaction(transaction);

    // 更新账户余额
    account->updateBalance(amount);

    return true;
}

// 取款操作
bool BankingSystem::withdraw(const string &accountId, double amount, const string &note)
{
    // 检查取款金额是否为正数
    if (amount <= 0)
    {
        cerr << "Error: Withdrawal amount must be positive." << endl;
        return false;
    }

    // 查找账户
    auto account = findAccount(accountId);
    if (!account)
    {
        cerr << "Error: Account not found." << endl;
        return false;
    }

    // 检查账户是否支持取款
    if (!account->canWithdraw())
    {
        cerr << "Error: This account type does not support withdrawals." << endl;
        return false;
    }

    // 检查余额是否充足
    if (account->getBalance() < amount)
    {
        cerr << "Error: Insufficient funds for withdrawal." << endl;
        return false;
    }

    // 创建交易记录
    auto transaction = make_shared<Transaction>(
        TransactionType::WITHDRAWAL,
        accountId,
        "", // 取款没有目标账户
        amount,
        note);

    // 记录交易
    recordTransaction(transaction);

    // 更新账户余额（取款为负数）
    account->updateBalance(-amount);

    return true;
}

// 转账操作
bool BankingSystem::transfer(const string &sourceAccountId, const string &destAccountId,
                             double amount, const string &note)
{
    // 检查转账金额是否为正数
    if (amount <= 0)
    {
        cerr << "Error: Transfer amount must be positive." << endl;
        return false;
    }

    // 查找源账户和目标账户
    auto sourceAccount = findAccount(sourceAccountId);
    auto destAccount = findAccount(destAccountId);

    // 检查账户是否存在
    if (!sourceAccount || !destAccount)
    {
        cerr << "Error: One or both accounts not found." << endl;
        return false;
    }

    // 检查源账户余额是否充足
    if (sourceAccount->getBalance() < amount)
    {
        cerr << "Error: Insufficient funds for transfer." << endl;
        return false;
    }

    // 检查储蓄账户的特殊转账规则：只能转账给同一客户的支票账户
    if (dynamic_cast<SavingsAccount *>(sourceAccount.get()))
    {
        bool isSameCustomer = sourceAccount->getOwnerName() == destAccount->getOwnerName();
        bool isDestChecking = dynamic_cast<CheckingAccount *>(destAccount.get()) != nullptr;

        if (!(isSameCustomer && isDestChecking))
        {
            cerr << "Error: Savings accounts can only transfer to the same customer's checking account." << endl;
            return false;
        }
    }

    // 创建交易记录
    auto transaction = make_shared<Transaction>(
        TransactionType::TRANSFER,
        sourceAccountId,
        destAccountId,
        amount,
        note);

    // 记录交易
    recordTransaction(transaction);

    // 更新账户余额
    sourceAccount->updateBalance(-amount);
    destAccount->updateBalance(amount);

    return true;
}

// 记录交易
void BankingSystem::recordTransaction(const shared_ptr<Transaction> &transaction)
{
    // 添加到全局交易列表
    allTransactions.push_back(transaction);

    // 添加到源账户的交易列表
    auto sourceAccount = findAccount(transaction->getSourceAccountId());
    if (sourceAccount)
    {
        sourceAccount->addTransaction(transaction);
    }

    // 如果是转账，也添加到目标账户的交易列表
    if (transaction->getType() == TransactionType::TRANSFER)
    {
        auto destAccount = findAccount(transaction->getDestinationAccountId());
        if (destAccount)
        {
            destAccount->addTransaction(transaction);
        }
    }
}

// 获取所有客户
vector<shared_ptr<Customer>> BankingSystem::getAllCustomers() const
{
    return customers;
}

// 获取所有账户
vector<shared_ptr<Account>> BankingSystem::getAllAccounts() const
{
    vector<shared_ptr<Account>> result;
    for (const auto &pair : accounts)
    {
        result.push_back(pair.second);
    }
    return result;
}

// 获取所有储蓄账户
vector<shared_ptr<Account>> BankingSystem::getSavingsAccounts() const
{
    vector<shared_ptr<Account>> result;
    for (const auto &pair : accounts)
    {
        if (dynamic_cast<SavingsAccount *>(pair.second.get()))
        {
            result.push_back(pair.second);
        }
    }
    return result;
}

// 获取所有支票账户
vector<shared_ptr<Account>> BankingSystem::getCheckingAccounts() const
{
    vector<shared_ptr<Account>> result;
    for (const auto &pair : accounts)
    {
        if (dynamic_cast<CheckingAccount *>(pair.second.get()))
        {
            result.push_back(pair.second);
        }
    }
    return result;
}

// 获取所有交易记录
vector<shared_ptr<Transaction>> BankingSystem::getAllTransactions() const
{
    return allTransactions;
}

// 生成交易报告
void BankingSystem::generateTransactionReport(const string &filename) const
{
    // 打开输出文件
    ofstream reportFile(filename);

    // 检查文件是否成功打开
    if (!reportFile.is_open())
    {
        cerr << "Error: Unable to create report file: " << filename << endl;
        return;
    }

    // 写入报告标题和系统概况
    reportFile << "===== Global Transactions Report =====" << endl;
    reportFile << "Total Customers: " << getTotalCustomerCount() << endl;
    reportFile << "Total Accounts: " << getTotalAccountCount() << endl;
    reportFile << "Total Transactions: " << allTransactions.size() << endl;
    reportFile << "Total Balance: ¥" << fixed << setprecision(2) << getTotalBalance() << endl;
    reportFile << "==============================================" << endl
               << endl;

    // 检查是否有交易记录
    if (allTransactions.empty())
    {
        reportFile << "No transactions found in the system." << endl;
    }
    else
    {
        // 写入交易历史记录标题
        reportFile << "Transaction History (chronological order):" << endl
                   << endl;

        // 按时间戳对交易记录进行排序
        vector<shared_ptr<Transaction>> sortedTransactions = allTransactions;
        sort(sortedTransactions.begin(), sortedTransactions.end(),
                  [](const shared_ptr<Transaction> &a, const shared_ptr<Transaction> &b)
                  {
                      return a->getTimestamp() < b->getTimestamp();
                  });

        // 遍历并输出每条交易记录
        for (const auto &transaction : sortedTransactions)
        {
            reportFile << "---------------------------------------------" << endl;
            reportFile << transaction->toString() << endl;
        }
    }

    // 关闭文件并显示成功信息
    reportFile.close();
    cout << "Report successfully generated as \"" << filename << "\"" << endl;
}

// 获取客户总数
int BankingSystem::getTotalCustomerCount() const
{
    return customers.size();
}

// 获取账户总数
int BankingSystem::getTotalAccountCount() const
{
    return accounts.size();
}

// 计算所有账户的总余额
double BankingSystem::getTotalBalance() const
{
    double total = 0.0;
    for (const auto &pair : accounts)
    {
        total += pair.second->getBalance();
    }
    return total;
}